package server;

import both.Question;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.xml.bind.*;;
import both.*;

public class GameShowServer extends AbstractFileListener {

    private String serverOutputFolder;
    private String clientOutputFolder;
    private String questionFile;
    private Game game;
    private HashMap<String, Long> lastMod = new HashMap<>();
    private static int numResponses = 0;
    private static int contestants;
    private static ServerGameTab gameTab;
    
    protected void listenerTick() throws Exception {
        FileFilter registFilter = new FileFilter() {
            @Override
            public boolean accept(File file) {
                String fname = file.getName();
                return fname.startsWith("register-");
            }
        };

        JAXBContext jaxbContext = JAXBContext.newInstance(Contestant.class);
        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
        for (File file : new File(clientOutputFolder).listFiles(registFilter)) {
            String clid = getFilenameId(file.getName());
            long currMod = file.lastModified();
            if (lastMod.containsKey(clid)) {
                long lastModif = lastMod.get(clid);
                if (currMod > lastModif) {
                    Contestant contest = (Contestant) jaxbUnmarshaller.unmarshal(file);
                    contest.setUniqueID(clid);
                    sendRegistrationEvent(contest, "update-registration");
                }
            } else {
                Contestant contest = (Contestant) jaxbUnmarshaller.unmarshal(file);
                contest.setUniqueID(clid);
                sendRegistrationEvent(contest, "new-registration");
            }
            lastMod.put(clid, currMod);
            setContestants(game.getRoster().contestantsByTeamName().size());
        }
    }

    private String getFilenameId(String fname) {
        return fname.split("-", 2)[1];
    }

    private void sendRegistrationEvent(Contestant contestant, String type) {
        ActionEvent ev = new ActionEvent(contestant, 0, type, System.currentTimeMillis(), 0);
        sendEvent(ev);
    }

    public void sendTestMessage() throws JAXBException {
        ArrayList<Contestant> contestants = getGame().getRoster().contestantsByTeamName();
        ArrayList<String> uids = new ArrayList<>(contestants.size());
        for (Contestant cont : contestants) {
            uids.add(cont.getUniqueID());
        }
        TestMessage msg = new TestMessage();
        msg.setIDs(uids);
        JAXBContext jaxbContext = JAXBContext.newInstance(TestMessage.class);
        Marshaller jaxbMarshall = jaxbContext.createMarshaller();
        jaxbMarshall.marshal(msg, new File(serverOutputFolder + "/test"));
    }

    //Sends question file
    public void sendQuestion(int index) throws JAXBException, IOException {
        resetResponses();
        Question question = game.getQuestionList().get(index);
        JAXBContext jaxbContext = JAXBContext.newInstance(Question.class);
        Marshaller jaxbMarshall = jaxbContext.createMarshaller();
        File tgfile = new File(serverOutputFolder + "/question");
        tgfile.createNewFile();
        jaxbMarshall.marshal(question, tgfile);

    }

    public void addRegistrationListener(ActionListener listen) {
        addListener(listen);
    }

    public void removeRegistrationListener(ActionListener listen) {
        removeListener(listen);
    }

    public HashMap<String, Answer> readAnswers() throws IOException, JAXBException {
        HashMap<String, Answer> ret = new HashMap<>();
        FileFilter ansFilter = new FileFilter() {
            @Override
            public boolean accept(File file) {
                return file.getName().startsWith("answer-");
            }
        };
        for (File file : new File(clientOutputFolder).listFiles(ansFilter)) {
            ret.put(getFilenameId(file.getName()), readAnswer(file));
        }
        return ret;
    }

    public static void checkResponses() {
        if (GameShowServer.getNumResponses() >= GameShowServer.getNumContestants()) {
            Server.changeGameTab();
            gameTab.go();
        }
    }

    private Answer readAnswer(File path) throws JAXBException {
        JAXBContext jaxbContext = JAXBContext.newInstance(Answer.class);
        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
        return (Answer) jaxbUnmarshaller.unmarshal(path);
    }

    public String getServerOutputFolder() {
        return serverOutputFolder;
    }

    public void setServerOutputFolder(String serverOutputFolder) {
        this.serverOutputFolder = serverOutputFolder;
    }

    public String getClientOutputFolder() {
        return clientOutputFolder;
    }

    public void setClientOutputFolder(String clientOutputFolder) {
        this.clientOutputFolder = clientOutputFolder;
    }

    public String getQuestionFile() {
        return questionFile;
    }

    public void setQuestionFile(String questionFile) throws Exception {
        this.questionFile = questionFile;
        game.setQuestionList(QuestionFileReader.readQuestionsFile(new File(questionFile)));
    }

    public Game getGame() {
        return game;
    }

    public ServerGameTab getGameTab() {
        return gameTab;
    }

    public void setGameTab(ServerGameTab gameTab) {
        this.gameTab = gameTab;
    }

    public void setGame(Game game) {
        this.game = game;
    }

    public static int getNumResponses() {
        return numResponses;
    }

    public static void tickResponses() {
        numResponses++;
    }

    public static void resetResponses() {
        numResponses = 0;
    }

    public static int getNumContestants() {
        return contestants;
    }

    public static void setContestants(int people) {
        contestants = people;
    }
}
